﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Engine.Cameras
{
    public class FppCamera:BaseCamera
    {
        #region Constructors

        public FppCamera(Game game):base(game)
        {            
        }

        #endregion

        #region Override

        public override void Initialize()
        {
            Mouse.SetPosition(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
            _originalMouseState = Mouse.GetState();
            base.Initialize();
        }
        public override void Update(GameTime gameTime)
        {
            ProcessInput();
            UpdateViewMatrix();            
            base.Update(gameTime);
        }

        #endregion

        #region Private Methods

        private void UpdateViewMatrix()
        {
            Matrix rotationMatrix = Matrix.CreateRotationX(XAngle) * Matrix.CreateRotationY(YAngle);
            Vector3 transformedReference = Vector3.Transform(Vector3.UnitZ, rotationMatrix);
            Vector3 cameraLookat = CameraPosition + transformedReference;
            ViewMatrix = Matrix.CreateLookAt(CameraPosition, cameraLookat, new Vector3(0.0f, 1.0f, 0.0f));
        }
        private void ProcessInput()
        {
            const float rotationSpeed = 1f / 1000f;
            const float forwardSpeed = 50f / 60f;

            MouseState currentMouseState = Mouse.GetState();
            if (currentMouseState != _originalMouseState)
            {
                float xDifference = currentMouseState.X - _originalMouseState.X;
                float yDifference = currentMouseState.Y - _originalMouseState.Y;
                Mouse.SetPosition(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
                YAngle += -xDifference * rotationSpeed;
                XAngle += yDifference * rotationSpeed;
            }

            KeyboardState keyboardState = Keyboard.GetState();

            if (keyboardState.IsKeyDown(Keys.W) || keyboardState.IsKeyDown(Keys.S))
            {
                Matrix rotationMatrix = Matrix.CreateRotationX(XAngle) * Matrix.CreateRotationY(YAngle);
                Vector3 forwardVec;

                if(keyboardState.IsKeyDown(Keys.W))
                    forwardVec = new Vector3(0, 0, forwardSpeed);
                else
                    forwardVec = new Vector3(0, 0, -forwardSpeed);

                forwardVec = Vector3.Transform(forwardVec, rotationMatrix);
                _cameraPosition.Z += forwardVec.Z;
                _cameraPosition.Y += forwardVec.Y;
                _cameraPosition.X += forwardVec.X;
            }            
        }

        #endregion

        #region Properties

        private Vector3 _cameraPosition;
        public override Vector3 CameraPosition
        {
            get { return _cameraPosition; }
            set { _cameraPosition = value; }
        }
        private float _yAngle;
        public float YAngle
        {
            get { return _yAngle; }
            set { _yAngle = value; }
        }
        private float _xAngle;
        public float XAngle
        {
            get { return _xAngle; }
            set { _xAngle = value; }
        }

        #endregion

        #region Fields
        
        private MouseState _originalMouseState;

        #endregion
    }
}
